package common.server.redis.redisson;

import java.util.*;
import java.util.concurrent.TimeUnit;

import common.server.redis.AbstractRedisResource;
import common.server.utils.JsonUtils;
import org.redisson.api.RList;
import org.redisson.api.RMap;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RedissonClient;

/**
 * @author Administrator
 * @version [版本号, 2017/11/22 0022]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class RedissonResource extends AbstractRedisResource<RedissonClient> {

	private RedissonClient redisson;

	protected RedissonResource(RedissonClient redisson) {
		this.redisson = redisson;
	}

	@Override
	public <T> T get(String key, Class<T> clazz) {
		return call((redisson) -> {
			String value = (String) redisson.getBucket(key).get();
			if (value == null) {
				return null;
			}
			if (clazz == String.class) {
				return (T) value;
			}
			return JsonUtils.fromJson(value, clazz);
		});
	}

	@Override
	public <T> T hget(String key, String field, Class<T> clazz) {
		return call((redisson) -> {
			String value = (String) redisson.getMap(key).get(field);
			if (value == null) {
				return null;
			}
			if (clazz == String.class) {
				return (T) value;
			}
			return JsonUtils.fromJson(value, clazz);
		});

	}

	@Override
	public Map<String, String> hgetAll(String key) {
		return call((redisson) -> {
			RMap<String, String> res = redisson.getMap(key);
			return res.readAllMap();
		});
	}

	@Override
	public Set<String> hkeys(String key) {
		return call((redisson) -> {
			RMap<String, String> res = redisson.getMap(key);
			return res.readAllKeySet();
		});
	}

	@Override
	public <T> List<T> hmget(String key, Class<T> clazz, String... fields) {
		return call((redisson) -> {
			RMap<String, String> res = redisson.getMap(key);
			Map<String, String> map = res
					.getAll(new HashSet(Arrays.asList(fields)));
			return toList(map.values(), clazz);
		});
	}

	@Override
	public <T> T lpop(String key, Class<T> clazz) {
		return call((redisson) -> {
			String value = (String) redisson.getDeque(key).poll();
			if (value == null) {
				return null;
			}
			if (clazz == String.class) {
				return (T) value;
			}
			return JsonUtils.fromJson(value, clazz);
		});
	}

	@Override
	public <T> T rpop(String key, Class<T> clazz) {
		return call((redisson) -> {
			String value = (String) redisson.getDeque(key).pollLast();
			if (value == null) {
				return null;
			}
			if (clazz == String.class) {
				return (T) value;
			}
			return JsonUtils.fromJson(value, clazz);
		});
	}

	@Override
	public List<String> lrange(String key, int start, int end) {
		return call((redisson) -> {
			RList<String> list = redisson.getList(key);
			List<String> value = list.subList(start, end).readAll();
			return value;
		});
	}

	@Override
	public long llen(String key) {
		return call((redisson) -> (long) redisson.getList(key).size());
	}

	@Override
	public <T> List<T> zrange(String key, int start, int end, Class<T> clazz) {
		return call((redisson) -> {
			RScoredSortedSet<String> list = redisson.getScoredSortedSet(key);
			return toList(list.valueRange(start, end), clazz);
		});
	}

	@Override
	public void set(String key, String value, long time) {
		call((redisson) -> {
			redisson.getBucket(key).set(value);
			if (time > 0) {
				redisson.getKeys().expire(key, time, TimeUnit.MILLISECONDS);
			}
			return null;
		});
	}
	
	@Override
	public Long setnx(String key, String value, long time) {
		
		return call((redisson) -> {
			Boolean setnxFlag = redisson.getBucket(key).trySet(value);
			Long lvalue;
			if (time > 0) {
				redisson.getKeys().expire(key, time, TimeUnit.MILLISECONDS);
			}
			if(setnxFlag){
				lvalue = 1l;
			}else{
				lvalue = 0l;
			}
			
			return lvalue;
			
		});
		
	}
	

	@Override
	public void del(String key) {
		call((redisson) -> {
			redisson.getKeys().delete(key);
			return null;
		});
	}

	@Override
	public void hset(String key, String field, String value, long time) {
		call((redisson) -> {
			redisson.getMap(key).put(field, value);
			if (time > 0) {
				redisson.getKeys().expire(key, time, TimeUnit.MILLISECONDS);
			}
			return null;
		});
	}

	@Override
	public Long hincrby(String key, String field) {

		return call((redisson) -> {
			Long value = Long.valueOf(redisson.getMap(key).addAndGet(field, 1).toString());
			return value;
		});
	}
	
	@Override
	public void hdel(String key, String field) {
		call((redisson) -> {
			redisson.getMap(key).fastRemove(field);
			return null;
		});
	}

	@Override
	public void hmset(String key, Map<String, String> hash, long time) {
		call((redisson) -> {
			redisson.getMap(key).putAll(hash);
			if (time > 0) {
				redisson.getKeys().expire(key, time, TimeUnit.MILLISECONDS);
			}
			return null;
		});
	}

	@Override
	public void lpush(String key, String... value) {
		call((redisson) -> {
			redisson.getDeque(key).addFirst(value);
			return null;
		});
	}

	@Override
	public void rpush(String key, String value) {
		call((redisson) -> {
			redisson.getList(key).add(value);
			return null;
		});
	}

	@Override
	public void expire(String key, long time) {
		call((redisson) -> {
			redisson.getKeys().expire(key, time, TimeUnit.MILLISECONDS);
			return null;
		});
	}

	@Override
	public void sadd(String key, String... value) {
		call((redisson) -> {
			redisson.getSet(key).add(value);
			return null;
		});
	}

	@Override
	public RedissonClient getRealResource() {
		return this.redisson;
	}

	@Override
	public void close() {
		// redisson不需要释放资源
	}

}
